package com.yixin.hospital.controller;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yixin.hospital.common.ApiResult;
import com.yixin.hospital.common.Constant;
import com.yixin.hospital.entity.bo.GodownDrugDetail;
import com.yixin.hospital.entity.bo.PageInfo;
import com.yixin.hospital.entity.bo.PurchaseOrderDetail;
import com.yixin.hospital.entity.domain.*;
import com.yixin.hospital.entity.dto.req.purchaseorder.GoDownDrugReqDTO;
import com.yixin.hospital.entity.vo.*;
import com.yixin.hospital.enums.DrugDepositoryOtpTypeEnum;
import com.yixin.hospital.enums.GoDownStatusEnum;
import com.yixin.hospital.mapper.extend.GoDownExtendMapper;
import com.yixin.hospital.service.*;
import com.yixin.hospital.utils.DateUtil;
import com.yixin.hospital.utils.JwtUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;


import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/input-godown")
@Api(value = "入库单管理", tags = "入库单管理")
public class InputGodownController {

    @Resource
    PurchaseOrderService purchaseOrderService;
    @Resource
    DeptService deptService;
    @Resource
    PurchaseOrderDrugService purchaseOrderDrugService;
    @Resource
    PurchaseOrderOperationService purchaseOrderOperationService;
    @Resource
    GodownDrugService godownDrugService;
    @Resource
    GoDownExtendMapper goDownExtendMapper;
    @Resource
    DrugService drugService;
    @Resource
    DrugDepositoryDrugService drugDepositoryDrugService;
    @Resource
    DrugDepositoryService drugDepositoryService;
    @Resource
    DrugFactoryService drugFactoryService;
    @Resource
    DrugDepositoryController drugDepositoryController;


    @GetMapping("/list2")
    @ApiOperation(value = "入库单列表")
    public ApiResult<?> list(HttpServletRequest request, @RequestParam int currentPage, @RequestParam int pageSize) {
        ApiResult<List<DrugDepositoryVo>> listApiResult = drugDepositoryController.availableList(request, DrugDepositoryOtpTypeEnum.INPUT.getCode());
        if (CollectionUtils.isEmpty(listApiResult.getData())) return ApiResult.success(listApiResult);
        List<Long> drugDepositoryIds = listApiResult.getData().stream().map(DrugDepositoryVo::getId).collect(Collectors.toList());
        IPage<GoDownDrugVo> page = goDownExtendMapper.pageVo(Page.of(currentPage, pageSize), drugDepositoryIds);
        PageInfo<GoDownDrugVo> pageInfo = new PageInfo<>();
        BeanUtil.copyProperties(page, pageInfo);
        for (GoDownDrugVo record : page.getRecords()) {
            long count = godownDrugService.count(new LambdaQueryWrapper<GodownDrug>().eq(GodownDrug::getCode, record.getCode()).eq(GodownDrug::getStatus, 0));
            if (count == 0) record.setStatus(1);
            else record.setStatus(0);
        }
        pageInfo.setRecords(BeanUtil.copyToList(page.getRecords(), GoDownDrugVo.class));
        return ApiResult.success(pageInfo);
    }

    @GetMapping("/listInfo")
    @ApiOperation(value = "入库单详情")
    public ApiResult<?> ListInfo(@RequestParam String code) {
        List<GoDownDrugVo> detailList = goDownExtendMapper.detail(code);
        return ApiResult.success(detailList);
    }

    @GetMapping("/detail")
    @ApiOperation(value = "入库单详情")
    public ApiResult<?> detail(@RequestParam int id, @RequestParam int deptId) {
        List<DrugDepository> drugDepositoryList = drugDepositoryService.list(new LambdaQueryWrapper<DrugDepository>().eq(DrugDepository::getDept, deptId));
        List<Long> drugDepositoryIds = drugDepositoryList.stream().map(DrugDepository::getId).collect(Collectors.toList());

        // 查询采购单详情
        PurchaseOrder purchaseOrder = purchaseOrderService.getById(id);
        PurchaseOrderDetailVO purchaseOrderDetailVO = new PurchaseOrderDetailVO();
        BeanUtils.copyProperties(purchaseOrder, purchaseOrderDetailVO);
        // 查询库房
        DrugDepository drugDepository = drugDepositoryService.getById(drugDepositoryIds.get(0));
        purchaseOrderDetailVO.setApplyDepository(drugDepository.getId());
        purchaseOrderDetailVO.setApplyDepositoryName(drugDepository.getName());
        // 查询部门名称
        Dept dept = deptService.getById(drugDepository.getDept());
        purchaseOrderDetailVO.setDept(dept.getId());
        purchaseOrderDetailVO.setDeptName(dept.getName());
        // 根据采购单id查询采购药品列表
        List<PurchaseOrderDrug> drugList = new ArrayList<>();
        List<PurchaseOrderOperation> operationList = new ArrayList<>();
        for (Long drugDepositoryId : drugDepositoryIds) {
            drugList.addAll(purchaseOrderDrugService.list(new LambdaQueryWrapper<PurchaseOrderDrug>().eq(PurchaseOrderDrug::getPurchaseOrderId, purchaseOrderDetailVO.getId()).eq(PurchaseOrderDrug::getDepositoryId, drugDepositoryId)));
            operationList.addAll(purchaseOrderOperationService.list(new LambdaQueryWrapper<PurchaseOrderOperation>().eq(PurchaseOrderOperation::getPurchaseOrderId, purchaseOrderDetailVO.getId()).eq(PurchaseOrderOperation::getTargetDepositoryId, drugDepositoryId)));
        }
        Map<String, List<PurchaseOrderOperation>> operationMap = this.operationToMap(operationList);
        // 定义采购总数量
        int purchasesDrugNum = 0;
        // 定义总的入库数
        int allGodownNum = 0;
        // 定义每个药品已入库数
        int drugGodownNum = 0;
        // 入库单
        List<PurchaseOrderDetail> purchaseOrderList = BeanUtil.copyToList(drugList, PurchaseOrderDetail.class);
        List<GodownDrug> godownDrugAllList = godownDrugService.list(new LambdaQueryWrapper<GodownDrug>().eq(GodownDrug::getPurchaseOrderId, id));
        Map<Long, List<GodownDrug>> godownMap = godownToMap(godownDrugAllList);
        for (PurchaseOrderDetail purchaseOrderDrug : purchaseOrderList) {
            String key = purchaseOrderDrug.getPurchaseOrderId() + purchaseOrderDrug.getDrugCode();
            List<PurchaseOrderOperationVo> purchaseOrderOperationVos = BeanUtil.copyToList(operationMap.get(key), PurchaseOrderOperationVo.class);
            if (CollectionUtils.isEmpty(purchaseOrderOperationVos)) continue;
            for (PurchaseOrderOperationVo orderOperation : purchaseOrderOperationVos) {
                purchasesDrugNum += orderOperation.getNum();
                List<GodownDrug> godownDrugListByOptId = godownMap.get(orderOperation.getId());
                if (!CollectionUtils.isEmpty(godownDrugListByOptId)) {
                    List<GodownDrugDetail> godownDrugDetailList = new ArrayList<>();
                    for (GodownDrug godownDrug : godownDrugListByOptId) {
                        allGodownNum += godownDrug.getPutNum();
                        GodownDrugDetail godownDrugDetail = new GodownDrugDetail();
                        godownDrugDetail.setId(godownDrug.getId());
                        godownDrugDetail.setDrugCode(godownDrug.getDrugCode());
                        godownDrugDetail.setOperationId(godownDrug.getOperationId());
                        godownDrugDetail.setProductTime(godownDrug.getProductTime());
                        godownDrugDetail.setExpirationTime(godownDrug.getExpiration());
                        godownDrugDetail.setGodownNum(godownDrug.getPutNum());
                        godownDrugDetail.setBatchCode(godownDrug.getBatchCode());
                        godownDrugDetailList.add(godownDrugDetail);
                    }
                    orderOperation.setGodownDrugList(godownDrugDetailList);
                }
            }
            purchaseOrderDrug.setOperationList(purchaseOrderOperationVos);

            // 查询药品表
            Drug drug = drugService.getOne(new LambdaQueryWrapper<Drug>().eq(Drug::getCode, purchaseOrderDrug.getDrugCode()));
            purchaseOrderDrug.setDrugCode(drug.getCode());
            purchaseOrderDrug.setDrugName(drug.getName());
            purchaseOrderDrug.setDrugCommonName(drug.getCommonName());
            purchaseOrderDrug.setDrugSpecs(drug.getSpecs());
            purchaseOrderDrug.setStatus(drug.getStatus());
            purchaseOrderDrug.setForm(drug.getForm());
            purchaseOrderDrug.setFactory(drugFactoryService.getById(drug.getFactory()).getFactory());
            purchaseOrderDrug.setOuterUnit(drug.getOuterUnit());
            purchaseOrderDrug.setMinPurchaseNum(drug.getMinPurchaseNum());
            purchaseOrderDrug.setBuyCycle(drug.getBuyCycle());
            // 库存
            LambdaQueryWrapper<DrugDepositoryDrug> DrugDepositoryDrugWrapper = new LambdaQueryWrapper<>();
            DrugDepositoryDrugWrapper.eq(DrugDepositoryDrug::getDrugCode, purchaseOrderDrug.getDrugCode());
            DrugDepositoryDrugWrapper.eq(DrugDepositoryDrug::getDrugDepositoryId, drugDepository.getId());
            DrugDepositoryDrugWrapper.select(DrugDepositoryDrug::getNums).groupBy(DrugDepositoryDrug::getDrugDepositoryId, DrugDepositoryDrug::getDrugCode);
            DrugDepositoryDrug drugDepositoryDrug = drugDepositoryDrugService.getOne(DrugDepositoryDrugWrapper);
            purchaseOrderDrug.setDepositoryNum(Objects.nonNull(drugDepositoryDrug) ? drugDepositoryDrug.getNums() : 0);
        }
        purchaseOrderDetailVO.setDrugNum(purchasesDrugNum);
        purchaseOrderDetailVO.setGodownStatus(allGodownNum == 0 ? GoDownStatusEnum.PENDING.getCode() :
                purchaseOrderDetailVO.getDrugNum() != allGodownNum ? GoDownStatusEnum.DOING.getCode() : GoDownStatusEnum.DONE.getCode());

        purchaseOrderDetailVO.setPurchaseOrderDrugList(purchaseOrderList);
        purchaseOrderDetailVO.setDrugTypeNum(drugList.size());
        return ApiResult.success(purchaseOrderDetailVO);
    }

    private Map<String, List<PurchaseOrderOperation>> operationToMap(List<PurchaseOrderOperation> operationList) {
        Map<String, List<PurchaseOrderOperation>> map = new HashMap<>();
        for (PurchaseOrderOperation purchaseOrderOperation : operationList) {
            String key = purchaseOrderOperation.getPurchaseOrderId() + purchaseOrderOperation.getDrugCode();
            List<PurchaseOrderOperation> purchaseOrderOperations = map.get(key);
            if (CollectionUtils.isEmpty(purchaseOrderOperations)) purchaseOrderOperations = new ArrayList<>();
            purchaseOrderOperations.add(purchaseOrderOperation);
            map.put(key, purchaseOrderOperations);
        }
        return map;
    }

    private Map<Long, List<GodownDrug>> godownToMap(List<GodownDrug> godownDrugs) {
        Map<Long, List<GodownDrug>> map = new HashMap<>();
        for (GodownDrug godownDrug : godownDrugs) {
            Long key = godownDrug.getOperationId();
            List<GodownDrug> godownDrugList = map.get(key);
            if (CollectionUtils.isEmpty(godownDrugList)) godownDrugList = new ArrayList<>();
            godownDrugList.add(godownDrug);
            map.put(key, godownDrugList);
        }
        return map;
    }

    @PostMapping("/godown-drug2")
    @ApiOperation(value = "预入库")
    @Transactional
    public ApiResult<?> goDownDrug2(@Valid @RequestBody GoDownDrugReqDTO goDownDrugReqDTO, HttpServletRequest request) {
        String userName = JwtUtil.getName(request.getHeader(Constant.AUTHORIZATION));
        List<GodownDrug> godownDrugList = new ArrayList<>();
        LambdaQueryWrapper<GodownDrug> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(GodownDrug::getCode).last("LIMIT 1");
        GodownDrug latestGodownDrug = godownDrugService.getOne(wrapper);
//      Integer cacheCodeSuffixNum = Objects.nonNull(CaffeineUtils.get(Constant.PURCHASE_CODE_PRE)) ? (Integer)CaffeineUtils.get(Constant.PURCHASE_CODE_PRE) : 1;   // 1
        int cacheCodeSuffixNum = 1;
        // 优先从 latestGodownDrug 中获取 code 后缀编号
        if (latestGodownDrug != null) {
            String code = latestGodownDrug.getCode();
            if (code != null && !code.isEmpty()) {
                try {
                    String subCode = code.substring(10);
                    cacheCodeSuffixNum = Integer.parseInt(subCode) + 1;
                } catch (NumberFormatException e) {
                    // 如果解析失败，记录日志并保持默认值
                    System.err.println("Invalid code format: " + code);
                }
            }
        }

        String codeSuffixNum = String.format("%03d", cacheCodeSuffixNum);   // 001
        String code = "CG" + DateUtil.dateToString(LocalDateTime.now(), DateUtil.YMN) + codeSuffixNum;  // CG20250401001
//        cacheCodeSuffixNum++;   // 2
//        CaffeineUtils.put(Constant.PURCHASE_CODE_PRE, cacheCodeSuffixNum);
        for (GoDownDrugReqDTO.GoDownDrugBO goDownDrugBO : goDownDrugReqDTO.getPurchaseOrderDrugList()) {
            GodownDrug godownDrug = new GodownDrug();
            godownDrug.setDrugCode(goDownDrugBO.getDrugCode());
            godownDrug.setPurchaseOrderId(goDownDrugReqDTO.getPurchaseOrderId());
            godownDrug.setOperationId(goDownDrugBO.getOperationId());
            godownDrug.setDrugDepositoryId(goDownDrugReqDTO.getDrugDepositoryId());
            godownDrug.setCode(code);
            godownDrug.setSupplier(goDownDrugBO.getSupplier());
            godownDrug.setSource(goDownDrugReqDTO.getSource());
            godownDrug.setSourceNum(goDownDrugBO.getSourceNum());
            godownDrug.setBatchCode(goDownDrugBO.getBatchCode());
            godownDrug.setProductTime(goDownDrugBO.getProductTime());
            godownDrug.setQualityTime(goDownDrugBO.getQualityTime());
            godownDrug.setExpiration(goDownDrugBO.getExpiration());
            godownDrug.setPutNum(goDownDrugBO.getPutNum());
            godownDrug.setCreatedBy(userName);
            godownDrug.setUpdatedBy(userName);
            godownDrugList.add(godownDrug);
        }
        godownDrugService.saveBatch(godownDrugList);

        // 入库房
//        List<DrugDepositoryDrug> addDrugDepositoryDrugList = new ArrayList<>();
//        List<DrugDepositoryDrug> updateDrugDepositoryDrugList = new ArrayList<>();
//        for (GoDownDrugReqDTO.GoDownDrugBO goDownDrugBO : goDownDrugReqDTO.getGoDownDrugBOList()) {
//            DrugDepositoryDrug drugDepositoryDrug = drugDepositoryDrugService.getOne(new LambdaQueryWrapper<DrugDepositoryDrug>()
//                    .eq(DrugDepositoryDrug::getDrugCode, goDownDrugBO.getDrugCode())
//                    .eq(DrugDepositoryDrug::getDrugDepositoryId, goDownDrugReqDTO.getDrugDepositoryId())
//                    .eq(DrugDepositoryDrug::getProductTime, goDownDrugBO.getProductTime())
//                    .eq(DrugDepositoryDrug::getExpiration, goDownDrugBO.getExpiration())
//            );
//            if (drugDepositoryDrug == null) {
//            DrugDepositoryDrug drugDepositoryDrug = new DrugDepositoryDrug();
//            drugDepositoryDrug.setDrugDepositoryId(goDownDrugReqDTO.getDrugDepositoryId());
//            drugDepositoryDrug.setDrugCode(goDownDrugBO.getDrugCode());
//            drugDepositoryDrug.setNum(goDownDrugBO.getNum());
//            drugDepositoryDrug.setProductTime(goDownDrugBO.getProductTime());
//            drugDepositoryDrug.setQualityTime(goDownDrugBO.getQualityTime());
//            drugDepositoryDrug.setExpiration(goDownDrugBO.getExpiration());
//            drugDepositoryDrug.setCreatedBy(userName);
//            drugDepositoryDrug.setUpdatedBy(userName);
//            addDrugDepositoryDrugList.add(drugDepositoryDrug);
//            } else {
//                // 可能导致数量有误，操作不频繁先不关心 应该是column = column + num
//                drugDepositoryDrug.setNum(drugDepositoryDrug.getNum() + goDownDrugBO.getNum());
//                drugDepositoryDrug.setUpdatedBy(userName);
//                updateDrugDepositoryDrugList.add(drugDepositoryDrug);
//            }
//        }
//        drugDepositoryDrugService.saveBatch(addDrugDepositoryDrugList);
//        drugDepositoryDrugService.updateBatchById(updateDrugDepositoryDrugList);

        return ApiResult.success();
    }

    @PostMapping("/godown-costPrice")
    @ApiOperation(value = "填进价入库")
    @Transactional
    public ApiResult<?> goDownDrug2(@Valid @RequestBody GoDownDrugVo goDownDrug, HttpServletRequest request) {
        String userName = JwtUtil.getName(request.getHeader(Constant.AUTHORIZATION));
        GodownDrug godownDrug = godownDrugService.getById(goDownDrug.getId());
        godownDrug.setSupplier(goDownDrug.getSupplier());
        godownDrug.setCostPrice(goDownDrug.getCostPrice());
        godownDrug.setStatus(1);
        godownDrug.setUpdatedTime(new Date());
        godownDrug.setUpdatedBy(userName);
        godownDrugService.updateById(godownDrug);
        // 入库房
        DrugDepositoryDrug existDrugDepositoryDrug = drugDepositoryDrugService.getOne(new LambdaQueryWrapper<DrugDepositoryDrug>()
                .eq(DrugDepositoryDrug::getDrugCode, goDownDrug.getDrugCode())
                .eq(DrugDepositoryDrug::getDrugDepositoryId, goDownDrug.getDrugDepositoryId())
                .eq(DrugDepositoryDrug::getProductTime, goDownDrug.getProductTime())
                .eq(DrugDepositoryDrug::getExpiration, goDownDrug.getExpiration())
        );
        if (existDrugDepositoryDrug == null) {
            DrugDepositoryDrug drugDepositoryDrug = new DrugDepositoryDrug();
            drugDepositoryDrug.setDrugDepositoryId(godownDrug.getDrugDepositoryId());
            drugDepositoryDrug.setDrugCode(godownDrug.getDrugCode());
            drugDepositoryDrug.setNum(godownDrug.getPutNum());
            drugDepositoryDrug.setProductTime(godownDrug.getProductTime());
            drugDepositoryDrug.setQualityTime(godownDrug.getQualityTime());
            drugDepositoryDrug.setExpiration(godownDrug.getExpiration());
            drugDepositoryDrug.setCreatedBy(userName);
            drugDepositoryDrug.setUpdatedBy(userName);
            drugDepositoryDrugService.save(drugDepositoryDrug);
        } else {
            // 可能导致数量有误，操作不频繁先不关心 应该是column = column + num
            existDrugDepositoryDrug.setNum(existDrugDepositoryDrug.getNum() + godownDrug.getPutNum());
            existDrugDepositoryDrug.setUpdatedBy(userName);
            drugDepositoryDrugService.updateById(existDrugDepositoryDrug);
        }
        return ApiResult.success();
    }


}
